package org.cybzacg.convert.factory;


import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.cybzacg.convert.annotation.Converter;
import org.cybzacg.convert.core.AbstractTypeConverter;
import org.cybzacg.convert.core.TypeConverter;
import org.cybzacg.convert.enums.ConversionPriority;
import org.cybzacg.convert.enums.RegistrationStatus;
import org.cybzacg.convert.model.RegistrationRecord;
import org.cybzacg.convert.model.RegistrationResult;
import org.cybzacg.convert.model.RegistrationStatistics;
import org.cybzacg.convert.scanner.ConverterScanner;
import org.cybzacg.convert.scanner.Filter;
import org.jetbrains.annotations.NotNull;


import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 自动转换器注册器
 * 提供基于注解和包扫描的自动注册功能
 *
 * <p>主要功能：
 * <ul>
 *   <li>自动扫描指定包路径下的转换器类</li>
 *   <li>根据@Converter注解自动配置转换器</li>
 *   <li>支持批量注册和条件注册</li>
 *   <li>提供注册统计和诊断信息</li>
 *   <li>支持热重载和动态更新</li>
 * </ul>
 *
 * <p>使用示例：
 * <pre>{@code
 * AutoConverterRegistrar registrar = new AutoConverterRegistrar();
 *
 * // 自动扫描并注册转换器
 * registrar.scanAndRegister("com.example.converters");
 *
 * // 扫描多个包
 * registrar.scanAndRegister(Arrays.asList(
 *     "com.example.converters",
 *     "com.example.custom"
 * ));
 *
 * // 使用过滤器注册
 * registrar.scanAndRegister("com.example.converters",
 *     ConverterScanner.Filters.ENABLED_ONLY);
 *
 * // 获取注册统计信息
 * RegistrationStatistics stats = registrar.getStatistics();
 * }</pre>
 *
 * @author cybzacg.blog
 * @version 3.0
 * @since 3.0
 */
@Slf4j
@Getter
public class AutoConverterRegistrar {

    /**
     * 转换器工厂
     */
    private final ConverterFactory converterFactory;

    /**
     * 转换器扫描器
     */
    private final ConverterScanner scanner;

    /**
     * 注册历史记录
     */
    private final Map<String, RegistrationRecord> registrationHistory = new ConcurrentHashMap<>();

    /**
     * 是否启用详细日志
     */
    @Setter
    private volatile boolean verboseLogging = false;

    /**
     * 默认构造方法
     */
    public AutoConverterRegistrar() {
        this(ConverterFactory.getInstance(), new ConverterScanner());
    }

    /**
     * 构造方法
     *
     * @param converterFactory 转换器工厂
     * @param scanner          扫描器
     */
    public AutoConverterRegistrar(ConverterFactory converterFactory, ConverterScanner scanner) {
        this.converterFactory = converterFactory != null ? converterFactory : ConverterFactory.getInstance();
        this.scanner = scanner != null ? scanner : new ConverterScanner();
    }

    /**
     * 扫描并注册指定包下的转换器
     *
     * @param packageName 包名
     * @return 注册统计信息
     */
    public RegistrationStatistics scanAndRegister(String packageName) {
        return scanAndRegister(Collections.singletonList(packageName), null);
    }

    /**
     * 扫描并注册指定包下的转换器
     *
     * @param packageName 包名
     * @param filter      过滤器
     * @return 注册统计信息
     */
    public RegistrationStatistics scanAndRegister(String packageName, Filter filter) {
        return scanAndRegister(Collections.singletonList(packageName), filter);
    }

    /**
     * 扫描并注册多个包下的转换器
     *
     * @param packageNames 包名列表
     * @return 注册统计信息
     */
    public RegistrationStatistics scanAndRegister(List<String> packageNames) {
        return scanAndRegister(packageNames, null);
    }

    /**
     * 扫描并注册多个包下的转换器
     *
     * @param packageNames 包名列表
     * @param filter       过滤器
     * @return 注册统计信息
     */
    public RegistrationStatistics scanAndRegister(List<String> packageNames, Filter filter) {
        long startTime = System.currentTimeMillis();

        log.info("开始自动注册转换器，扫描包: {}", packageNames);

        // 扫描转换器类
        List<Class<?>> converterClasses = scanner.scan(packageNames, filter);

        // 注册转换器
        List<RegistrationResult> results = new ArrayList<>();
        int successCount = 0;
        int failureCount = 0;
        int skippedCount = 0;

        for (Class<?> converterClass : converterClasses) {
            try {
                RegistrationResult result = registerConverter(converterClass);
                results.add(result);

                switch (result.status()) {
                    case SUCCESS:
                        successCount++;
                        break;
                    case FAILURE:
                        failureCount++;
                        break;
                    case SKIPPED:
                        skippedCount++;
                        break;
                }

            } catch (Exception e) {
                failureCount++;
                RegistrationResult result = new RegistrationResult(
                        converterClass, RegistrationStatus.FAILURE,
                        "注册过程中发生异常: " + e.getMessage(), null);
                results.add(result);

                log.error("注册转换器 {} 时发生异常", converterClass.getName(), e);
            }
        }

        long duration = System.currentTimeMillis() - startTime;

        // 创建统计信息
        RegistrationStatistics statistics = new RegistrationStatistics(
                packageNames, converterClasses.size(), successCount,
                failureCount, skippedCount, duration, results);

        // 记录注册历史
        String historyKey = String.join(",", packageNames) + ":" + System.currentTimeMillis();
        registrationHistory.put(historyKey, new RegistrationRecord(historyKey, statistics));

        log.info("自动注册完成，统计信息: {}", statistics);

        return statistics;
    }

    /**
     * 注册单个转换器类
     *
     * @param converterClass 转换器类
     * @return 注册结果
     */
    public RegistrationResult registerConverter(Class<?> converterClass) {
        if (verboseLogging) {
            log.debug("尝试注册转换器类: {}", converterClass.getName());
        }

        // 检查类有效性
        String validationError = validateConverterClass(converterClass);
        if (validationError != null) {
            if (verboseLogging) {
                log.debug("转换器类验证失败: {} - {}", converterClass.getName(), validationError);
            }
            return new RegistrationResult(converterClass, RegistrationStatus.SKIPPED, validationError, null);
        }

        try {
            // 获取注解信息
            Converter annotation = converterClass.getAnnotation(Converter.class);

            // 创建转换器实例
            TypeConverter converter = createConverterInstance(converterClass, annotation);

            // 注册到工厂
            converterFactory.registerConverter(converter);

            if (verboseLogging) {
                log.debug("成功注册转换器: {} ({})", converter.getName(), converterClass.getName());
            }

            return new RegistrationResult(converterClass, RegistrationStatus.SUCCESS, null, converter);

        } catch (Exception e) {
            String errorMessage = "创建转换器实例失败: " + e.getMessage();
            log.error("注册转换器 {} 失败: {}", converterClass.getName(), errorMessage, e);
            return new RegistrationResult(converterClass, RegistrationStatus.FAILURE, errorMessage, null);
        }
    }

    /**
     * 验证转换器类
     *
     * @param converterClass 转换器类
     * @return 验证错误信息，如果验证通过返回null
     */
    private String validateConverterClass(Class<?> converterClass) {
        // 检查注解
        if (!converterClass.isAnnotationPresent(Converter.class)) {
            return "缺少@Converter注解";
        }

        // 检查接口实现
        if (!TypeConverter.class.isAssignableFrom(converterClass)) {
            return "未实现TypeConverter接口";
        }

        // 检查是否为抽象类或接口
        if (converterClass.isInterface() || java.lang.reflect.Modifier.isAbstract(converterClass.getModifiers())) {
            return "不能是抽象类或接口";
        }

        // 检查构造方法
        try {
            converterClass.getDeclaredConstructor();
        } catch (NoSuchMethodException e) {
            return "缺少无参构造方法";
        }

        // 检查注解配置
        Converter annotation = converterClass.getAnnotation(Converter.class);
        if (!annotation.enabled()) {
            return "转换器被禁用";
        }

        return null;
    }

    /**
     * 创建转换器实例
     *
     * @param converterClass 转换器类
     * @param annotation     注解
     * @return 转换器实例
     * @throws Exception 创建失败时抛出异常
     */
    private TypeConverter createConverterInstance(Class<?> converterClass, Converter annotation) throws Exception {
        // 创建实例
        TypeConverter converter = (TypeConverter) converterClass.getDeclaredConstructor().newInstance();

        // 如果是AbstractTypeConverter的子类，应用注解配置
        if (converter instanceof AbstractTypeConverter abstractConverter) {

            // 设置优先级
            if (annotation.priority() != ConversionPriority.MEDIUM) {
                // 这里可能需要在AbstractTypeConverter中添加setPriority方法
                // 或者通过反射设置优先级字段
                try {
                    java.lang.reflect.Field priorityField = AbstractTypeConverter.class.getDeclaredField("priority");
                    priorityField.setAccessible(true);

                    priorityField.set(abstractConverter, annotation.priority().getValue());
                } catch (Exception e) {
                    log.debug("无法设置转换器优先级: {}", e.getMessage());
                }
            }

            // 设置启用状态
            try {
                java.lang.reflect.Field enabledField = AbstractTypeConverter.class.getDeclaredField("enabled");
                enabledField.setAccessible(true);
                enabledField.set(abstractConverter, annotation.enabled());
            } catch (Exception e) {
                log.debug("无法设置转换器启用状态: {}", e.getMessage());
            }
        }

        return converter;
    }

    /**
     * 重新扫描并注册转换器
     * 清除之前的扫描缓存并重新注册
     *
     * @param packageNames 包名列表
     * @return 注册统计信息
     */
    public RegistrationStatistics rescanAndRegister(List<String> packageNames) {
        log.info("重新扫描并注册转换器");
        converterFactory.clearAllConverters();
        scanner.clearCache();
        return scanAndRegister(packageNames);
    }

    /**
     * 获取注册历史记录
     *
     * @return 注册历史记录列表
     */
    public List<RegistrationRecord> getRegistrationHistory() {
        return new ArrayList<>(registrationHistory.values());
    }

    /**
     * 清除注册历史记录
     */
    public void clearRegistrationHistory() {
        registrationHistory.clear();
        log.debug("清除注册历史记录");
    }

    /**
     * 获取当前注册统计信息
     *
     * @return 统计信息
     */
    public RegistrationStatistics getCurrentStatistics() {
        return new RegistrationStatistics(
                Collections.emptyList(),
                converterFactory.getAllConverters().size(),
                (int) converterFactory.getAllConverters().stream().filter(TypeConverter::isEnabled).count(),
                0, 0, 0, Collections.emptyList()
        );
    }



    @Override
    public String toString() {
        return String.format("AutoConverterRegistrar{扫描器=%s, 详细日志=%s, 历史记录=%d}",
                scanner, verboseLogging, registrationHistory.size());
    }
}
